package com.bst.bsj.bops.web.biz.mongo;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

/**   
* @Title: AbstractMongoDao.java
* @Package com.bst.bsj.bops.web.biz.mongo
* @Description: TODO(mongodb dao操作封装)
* @author wangxiaojun
* @date 2016年4月13日 上午11:31:07
* @version V1.0
* Copyright (c) 2015, 博思堂博视界.
*/
public abstract class AbstractMongoDao<T> {

  private static final Log logger = LogFactory.getLog(AbstractMongoDao.class);

  @Autowired
  protected MongoTemplate mongoTemplate;

  /** 
   * 新增 
   * @param user 
   */
  public void insert(T t) {
    this.mongoTemplate.insert(t);
  }

  /** 
   * 批量新增 
   * @param users 
   */
  public void insertAll(List<T> t) {
    this.mongoTemplate.insertAll(t);
  }

  /**
   * 根据Id从Collection中查询对象              
   * @param id
   *                 实体对象的Id,对应Collection中记录的_id字段. 
   *                 <p>
   *                     需要说明的是,Mongdo自身没有主键自增机制.解决方法
   *                     <ol>
   *                         <li>实体入库的时候,程序中为实体赋主键值.
   *                         <li>实体入库的时候,在mongodb中自定义函数实现主键自增机制.定义方法同js代码类似
   *                     </ol>
   *                 </p>
   * @return
   */
  public T queryById(String id) {
    Query query = new Query();
    Criteria criteria = Criteria.where("id").is(id);
    query.addCriteria(criteria);
    logger.info("[Mongo Dao ]queryById:" + query);
    return this.mongoTemplate.findOne(query, this.getEntityClass());
  }

  /**
   * 根据条件查询集合              
   * @param query        
   *                     查询条件
   * @return
   *                     满足条件的集合
   */
  public List<T> queryList(Query query) {
    logger.info("[Mongo Dao ]queryList:" + query);
    return this.mongoTemplate.find(query, this.getEntityClass());
  }

  /**
     * 通过条件查询单个实体              
     * @param query
     * @return
     */
  public T queryOne(Query query) {
    logger.info("[Mongo Dao ]queryOne:" + query);
    return this.mongoTemplate.findOne(query, this.getEntityClass());
  }

  /**
   * 通过条件进行分页查询               
   * @param query
   *                     查询条件
   * @param start
   *                     查询起始值 
   *                     <strong> 类似mysql查询中的 limit start, size 中的 start</strong>
   * @param size
   *                     查询大小
   *                     <strong> 类似mysql查询中的 limit start, size 中的 size</strong>
   * @return
   *                     满足条件的集合
   */
  public List<T> getPage(Query query, int start, int size) {
    query.skip(start);
    query.limit(size);
    logger.info("[Mongo Dao ]queryPage:" + query + "(" + start + "," + size + ")");
    List<T> lists = this.mongoTemplate.find(query, this.getEntityClass());
    return lists;
  }

  /**
   * 根据条件查询库中符合记录的总数,为分页查询服务              
   * @param query
   *                     查询条件
   * @return
   *                     满足条件的记录总数
   */
  public Long getPageCount(Query query) {
    logger.info("[Mongo Dao ]queryPageCount:" + query);
    return this.mongoTemplate.count(query, this.getEntityClass());
  }

  /**
   * 根据Id删除操作
   *             
   * @param id
   */
  public void deleteById(String Id) {
    Criteria criteria = Criteria.where("id").in(Id);
    if (null != criteria) {
      Query query = new Query(criteria);
      logger.info("[Mongo Dao ]deleteById:" + query);
      T t = this.queryOne(query);
      if (null != query && t != null) {
        this.delete(t);
      }
    }
  }

  /**
   * 删除对象操作
   *           
   * @param t
   */
  public void delete(T t) {
    logger.info("[Mongo Dao ]delete:" + t);
    this.mongoTemplate.remove(t);
  }

  /** 
   * 删除全部 
   */
  public void deleteAll() {
    this.mongoTemplate.dropCollection(this.getEntityClass());
  }

  /**
   * 更新满足条件的第一个记录
   *              
   * @param query
   * @param update
   */
  public void updateFirst(Query query, Update update) {
    logger.info("[Mongo Dao ]updateFirst:query(" + query + "),update(" + update + ")");
    this.mongoTemplate.updateFirst(query, update, this.getEntityClass());
  }

  /**
   * 更新满足条件的所有记录
   *                
   * @param query
   * @param update
   */
  public void updateMulti(Query query, Update update) {
    logger.info("[Mongo Dao ]updateMulti:query(" + query + "),update(" + update + ")");
    this.mongoTemplate.updateMulti(query, update, this.getEntityClass());
  }

  protected abstract Class<T> getEntityClass();

  /**
   * 为属性自动注入bean服务              
   * @param mongoTemplate
   */
  public void setMongoTemplate(MongoTemplate mongoTemplate) {
    this.mongoTemplate = mongoTemplate;
  }

}
